package com.guguskins.back.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guguskins.back.common.constant.InventoryConstant;
import com.guguskins.back.common.constant.PrizeType;
import com.guguskins.back.common.constant.RecordConstant;
import com.guguskins.back.common.exception.GlobalMsgException;
import com.guguskins.back.common.websocket.PayWebSocketServer;
import com.guguskins.back.entity.GuDisCountOrUser;
import com.guguskins.back.entity.GuOrder;
import com.guguskins.back.entity.GuSystemConfig;
import com.guguskins.back.entity.GuUser;
import com.guguskins.back.entity.bo.TopUpBo;
import com.guguskins.back.entity.vo.PageVo;
import com.guguskins.back.entity.vo.ResultVo;
import com.guguskins.back.entity.vo.TopUpVo;
import com.guguskins.back.mapper.GuOrderMapper;
import com.guguskins.back.service.*;
import com.guguskins.back.utils.CommonUtil;
import com.guguskins.back.utils.DateUtil;
import com.guguskins.back.utils.pay.Unionpay;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 充值订单表 服务实现类
 * </p>
 *
 * @author mybatis-plus
 * @since 2021-05-10
 */
@Service
@Slf4j
public class GuOrderServiceImpl extends ServiceImpl<GuOrderMapper, GuOrder> implements GuOrderService {

    @Autowired
    private GuOrderMapper orderMapper;

    @Autowired
    private GuUserService userService;

    @Autowired
    private GuSystemConfigService systemConfigService;

    @Autowired
    private GuDisCountOrUserService disCountOrUserService;

    @Autowired
    private GuCurrencyRecordService currencyRecordService;

    @Autowired
    private GuRecordService recordService;

    @Autowired
    private GuTurntableService turntableService;

    @Override
    public TopUpVo cal(TopUpBo topUpBo) {
        TopUpVo topUpVo = new TopUpVo();

        //查询用户
        GuUser user = userService.getById(topUpBo.getUserId());
        if (ObjectUtils.isEmpty(user)) {
            throw new GlobalMsgException("用户状态异常");
        }
        GuSystemConfig systemConfig = systemConfigService.getSystemConfig();

        //计算价格
        BigDecimal orderAmount = topUpBo.getPayAmount().multiply(systemConfig.getConfigExchangeRate());
        topUpVo.setOrderAmount(orderAmount);

        //查询优惠券
        //根据用户id和优惠券码查询优惠券，为空或过期直接抛异常
        GuDisCountOrUser disCount = disCountOrUserService.findByDisCount(topUpBo.getCouponCode());
        if (!ObjectUtils.isEmpty(disCount) && disCount.getDcThreshold().compareTo(topUpBo.getPayAmount()) <= 0) {
            topUpVo.setCouponAmount(orderAmount.multiply(disCount.getDcDiscountSize()));
        }

        //计算邀请码
        if (!ObjectUtils.isEmpty(topUpBo.getInviteCode()) && !ObjectUtils.isEmpty(userService.checkInviteCode(topUpBo.getUserId(), topUpBo.getInviteCode()))) {
            topUpVo.setInviteAmount(orderAmount.multiply(systemConfigService.getSystemConfig().getConfigInvitePayReward()));
        }
        return topUpVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> topUp(TopUpBo topUpBo) {
        //查询用户
        GuUser user = userService.getById(topUpBo.getUserId());
        if (ObjectUtils.isEmpty(user)) {
            throw new GlobalMsgException("用户状态异常");
        }
        GuSystemConfig systemConfig = systemConfigService.getSystemConfig();

        //插入订单
        GuOrder order = new GuOrder();

        //生成订单号
        String sn = CommonUtil.generateSn(Unionpay.MSG_SRC_ID);
        order.setOrderSn(sn);
        order.setOrderUserId(user.getUserId());
        order.setOrderSteamId(user.getUserSteamId());
        order.setOrderUserNickname(user.getUserNickname());
        order.setOrderPayAmount(topUpBo.getPayAmount());
        order.setOrderState(1);

        // 计算价格（添加邀请码）
        BigDecimal orderAmount = order.getOrderPayAmount().multiply(systemConfig.getConfigExchangeRate());

        //查询优惠券
        //根据用户id和优惠券码查询优惠券，为空或过期直接抛异常
        GuDisCountOrUser disCount = disCountOrUserService.findByDisCount(topUpBo.getCouponCode());
        BigDecimal couponPrice = BigDecimal.ZERO;
        if (!ObjectUtils.isEmpty(disCount) && disCount.getDcThreshold().compareTo(topUpBo.getPayAmount()) <= 0) {
            couponPrice = orderAmount.multiply(disCount.getDcDiscountSize());
            order.setOrderCouponId(disCount.getDuDisCountId());
            order.setOrderCouponCode(disCount.getDuCounponCode());
        }

        //计算邀请码
        BigDecimal invitePrice = BigDecimal.ZERO;
        if (!ObjectUtils.isEmpty(topUpBo.getInviteCode())) {
            GuUser inviteUser = userService.checkInviteCode(topUpBo.getUserId(), topUpBo.getInviteCode());
            if (!ObjectUtils.isEmpty(inviteUser)) {
                invitePrice = orderAmount.multiply(systemConfigService.getSystemConfig().getConfigInvitePayReward());
                order.setOrderInviteUserId(inviteUser.getUserId());
                order.setOrderInviteSteamId(inviteUser.getUserSteamId());
                order.setOrderInviteCode(topUpBo.getInviteCode());
            }
        }

        order.setOrderAmount(orderAmount.add(couponPrice).add(invitePrice));

        if (order.insert()) {
            //调用第三方支付
            //返回链接
            JSONObject pay = Unionpay.pay(sn, DateUtil.getDate("yyyy-MM-dd"), topUpBo.getPayAmount().multiply(new BigDecimal(100)).intValue(), systemConfig.getConfigUri());
//            pay.getString()
            log.info("用户：{}，获取银联二维码接口响应结果：{}", user.getUserId(), pay);
            if (!"SUCCESS".equals(pay.getString("errCode"))) {
                log.error("用户id{}，昵称：{}，下单失败：{}", user.getUserId(), user.getUserNickname(), pay.getString("errCode"));
                throw new GlobalMsgException("下单失败");
            }
            return new HashMap<String, Object>(2) {
                {
                    put("orderId", order.getOrderId());
                    put("content", pay.getString("billQRCode"));
                }
            };
        }
        return null;
    }

    @Override
    public void callback(String billNo, String billStatus, String msg) {
        GuOrder order = this.getOne(new LambdaQueryWrapper<GuOrder>() {
            {
                eq(GuOrder::getOrderSn, billNo);
            }
        });
        boolean flag = false;
        if (!ObjectUtils.isEmpty(order)) {
            switch (billStatus) {
                case "PAID":
                    order.setOrderState(3);
                    //添加咕币
                    //1 充值 2 分红 3 填写邀请码 4 兑换 5 孵化 6 开箱子 7 退款
                    userService.addGuCurrency(order.getOrderUserId(), order.getOrderAmount(), order.getOrderAmount(), 1, order.getOrderId(), null, null, null, null);
                    //是否有邀请码
                    if (!ObjectUtils.isEmpty(order.getOrderInviteUserId())) {
                        BigDecimal inviteCurrency = order.getOrderAmount().multiply(systemConfigService.getSystemConfig().getConfigInvitePayReward());
                        userService.addGuCurrency(order.getOrderInviteUserId(), inviteCurrency, order.getOrderAmount(), 2, order.getOrderUserId(), null, null, null, null);
                    }
                    //是否含有优惠券
                    if (!ObjectUtils.isEmpty(order.getOrderCouponId())) {
                        GuDisCountOrUser disCountOrUser = disCountOrUserService.getById(order.getOrderCouponId());
                        disCountOrUser.setDuIsUse(0);
                        disCountOrUser.updateById();
                        recordService.addRecord(order.getOrderUserId(), RecordConstant.TYPE.USE, InventoryConstant.Source.PAY, order.getOrderId(), PrizeType.PROP, disCountOrUser.getDuId(), "充值使用道具卡", null);
                    }
                    //每日抽奖
                    turntableService.luckyDrawLimit(order.getOrderUserId(), order.getOrderPayAmount());
                    flag = true;
                    break;
                case "UNPAID":
                    order.setOrderState(1);
                    break;
                case "REFUND":
                    order.setOrderState(5);
                    break;
                case "CLOSED":
                case "UNKNOWN":
                default:
                    order.setOrderState(6);
                    break;
            }
            order.setOrderPayCallbackTime(LocalDateTime.now());
            order.setOrderMsg(msg);
        }
        order.updateById();
        try {
            PayWebSocketServer.sendInfo(JSON.toJSONString(flag ? ResultVo.success("充值成功") : ResultVo.fail("充值失败")), order.getOrderId().toString());
        } catch (IOException e) {
            log.error("推送前端失败：{}，错误：{}", order.getOrderId().toString(), e);
        }
    }

    @Override
    public PageVo<GuOrder> backPage(int p, int size, String startTime, String endTime, int orderState, String searchKey) {

        IPage<GuOrder> page = new Page<>(p, size);
        page = this.page(page, new LambdaQueryWrapper<GuOrder>() {
            {
                eq(orderState > 0, GuOrder::getOrderState, orderState);
                ge(!ObjectUtils.isEmpty(startTime), GuOrder::getOrderCreateTime, startTime);
                le(!ObjectUtils.isEmpty(endTime), GuOrder::getOrderCreateTime, endTime);
                like(!ObjectUtils.isEmpty(searchKey), GuOrder::getOrderSteamId, searchKey);
                like(!ObjectUtils.isEmpty(searchKey), GuOrder::getOrderUserNickname, searchKey);
            }
        });

        return new PageVo<>(page.getRecords(), page.getTotal());
    }

    @Override
    public boolean backRefund(Long orderId) {

        GuOrder order = this.getById(orderId);
        if (ObjectUtils.isEmpty(order)) {
            return false;
        }
        String refundDate = DateUtil.getDate("yyyy-MM-dd HH:mm:ss");
        JSONObject refundResult = Unionpay.refund(order.getOrderSn(), refundDate, order.getOrderPayAmount().multiply(new BigDecimal(100)).intValue());
        String billStatus = refundResult.getString("billStatus");
        switch (billStatus) {
            case "PAID":
                order.setOrderState(3);
                //添加咕币
                break;
            case "UNPAID":
                order.setOrderState(1);
                break;
            case "REFUND":
                order.setOrderState(5);
                userService.subtractGuCurrency(order.getOrderUserId(), order.getOrderAmount(), order.getOrderAmount(), 7, orderId, null, null, null, null);
                break;
            case "CLOSED":
            case "UNKNOWN":
            default:
                order.setOrderState(6);
                break;
        }
        order.setOrderRefundCallbackTime(DateUtil.strToLocalDateTime(refundDate));
        order.setOrderRefundMsg(JSON.toJSONString(refundResult));
        return order.updateById();
    }

    public static void main(String[] args) {
        BigDecimal one = BigDecimal.ONE;
        BigDecimal zero = BigDecimal.ZERO;
        System.err.println(one.compareTo(zero));
    }


}
